<!-- 商品列表创建 -->
<template>
    <div>
        <!-- 商品(spu)介绍 -->
        <el-card class="intro-card">
            <h4>商品(spu)介绍</h4>
            <el-form :model="dataForm" label-position="right" label-width="120px" ref="ruleFormRef" :rules="formRules">
                <el-form-item label="商品名称" prop="title">
                    <el-input v-model="dataForm.title" />
                </el-form-item>
                <el-form-item label="原始价格" prop="originalPrice">
                    <el-input v-model="dataForm.originalPrice">
                        <template #append>元</template>
                    </el-input>
                </el-form-item>
                <el-form-item label="当前价格" prop="price">
                    <el-input v-model="dataForm.price">
                        <template #append>元</template>
                    </el-input>
                </el-form-item>
                <el-form-item label="VIP价格" prop="vipPrice">
                    <el-input v-model="dataForm.vipPrice">
                        <template #append>元</template>
                    </el-input>
                </el-form-item>
                <el-form-item label="剩余库存">
                    <el-input :disabled="true" />
                </el-form-item>
                <el-form-item label="运费模板">
                    <el-select v-model="dataForm.freightTemplateId" placeholder="请选择运费模板" clearable>
                        <el-option v-for="item in freightData" :key="item.id" :label="item.title" :value="item.id" />
                    </el-select>
                </el-form-item>
                <el-form-item label="是否在售" prop="status">
                    <el-radio-group v-model="dataForm.status">
                        <el-radio :label="1">在售</el-radio>
                        <el-radio :label="0">下架</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="商品图片">
                    <el-upload v-model="dataForm.imgList" action="http://192.168.1.188:8080/upload/admin"
                        :headers="headers" list-type="picture-card" :limit="5" :on-success="handleAvatarSuccess"
                        :before-upload="beforeAvatarUpload" :on-exceed="exceedTips">
                        <el-icon>
                            <Plus />
                        </el-icon>
                    </el-upload>
                </el-form-item>
                <el-form-item label="商品单位" prop="unit">
                    <el-input v-model="dataForm.unit" placeholder="件 / 个 / 盒" />
                </el-form-item>
                <el-form-item label="所属类目">
                    <el-cascader v-model="dataForm.categoryId" placeholder="选择类目" :options="categoryTreeData" clearable
                        :props="{ emitPath: false, label: 'title', value: 'id', children: 'childrenList' }" />
                </el-form-item>
                <el-form-item label="商品简介">
                    <el-input v-model="dataForm.description" />
                </el-form-item>
                <el-form-item label="商品详细介绍" prop="detail">
                    <RichText v-model="dataForm.detail" style="width: 100%;" />
                </el-form-item>
            </el-form>
        </el-card>
        <!-- 商品参数表格 -->
        <el-card class="ShopParam-card">
            <h4>商品参数</h4>
            <el-button type="primary" plain @click="WaresParamsAdd">添加</el-button>
            <el-table :data="dataForm.attributeList" style="width:100%" :cell-style="{ textAlign: 'center' }"
                :header-cell-style="{ 'text-align': 'center' }">
                <el-table-column prop="attribute" label="商品参数名称" />
                <el-table-column prop="value" label="商品参数值" />
                <el-table-column label="操作" align="right">
                    <template #default="scope">
                        <el-button type="danger" @click="handleWaresDelete(scope.$index)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <!-- 规格维度表格 -->
        <el-card class="norms-card">
            <h4>规格维度</h4>
            <el-button type="primary" plain @click="normsFormAdd">添加</el-button>
            <el-table :data="dataForm.specificationList" style="width:100%" :cell-style="{ textAlign: 'center' }"
                :header-cell-style="{ 'text-align': 'center' }">
                <el-table-column prop="id" label="维度Id" />
                <el-table-column prop="title" label="维度名称" />
                <el-table-column prop="gmtCreate" label="创建时间">
                    <template #default="scope">
                        {{ formatTime(scope.row.gmtCreate) }}
                    </template>
                </el-table-column>
                <el-table-column label="操作">
                    <template #default="scope">
                        <el-button type="primary" @click="handleNormsEdit(scope.$index, scope.row)">修改</el-button>
                        <el-button type="danger" @click="handleNormsDelete(scope.$index)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <!-- 商品(Sku)详情表格 -->
        <el-card class="details-card">
            <template #header>
                <div class="card-header">
                    <h4>商品(Sku)详情</h4>
                    <el-button type="primary" plain @click="batchPricing" :disabled="dataForm.skuList.length == 0">
                        批量定价
                    </el-button>
                </div>
            </template>
            <div v-for="(item, index) in dataForm.specificationList" class="skuTag" :key="index">
                <el-tag type="warning">{{ item.title }}</el-tag>
                <el-tag v-for="(ites, ind) in item.values" closable @close="handleClose(ind, item)">
                    {{ ites }}
                </el-tag>
                <el-input v-if="item.inputSkuTagVisible" v-model="inputTag" class="skuInput"
                    @keyup.enter="handleInputConfirm(item)" @blur="handleInputConfirm(item)" />
                <el-button v-else size="small" @click="handleInputAdd(item)">
                    +添加
                </el-button>
            </div>
            <el-table :data="dataForm.skuList" style="width:100%" border :cell-style="{ textAlign: 'center' }"
                :header-cell-style="{ 'text-align': 'center' }" :span-method="objectSpanMethod">
                <el-table-column v-for="item in dataForm.specificationList" :prop="'id_' + item.title"
                    :label="item.title" />
                <el-table-column prop="id" label="SkuId" width="85" />
                <el-table-column label="¥价格(元)" width="145">
                    <template #default="scope">
                        <el-input-number v-model="scope.row.price" size="small" />
                    </template>
                </el-table-column>
                <el-table-column label="¥VIP价(元)" width="145">
                    <template #default="scope">
                        <el-input-number v-model="scope.row.vipPrice" size="small" />
                    </template>
                </el-table-column>
                <el-table-column label="¥吊牌价(元)" width="145">
                    <template #default="scope">
                        <el-input-number v-model="scope.row.originalPrice" size="small" />
                    </template>
                </el-table-column>
                <el-table-column label="库存(件)" width="145">
                    <template #default="scope">
                        <el-input-number v-model="scope.row.stock" size="small" />
                    </template>
                </el-table-column>
                <el-table-column label="重量(克)" width="145">
                    <template #default="scope">
                        <el-input-number v-model="scope.row.weighe" size="small" />
                    </template>
                </el-table-column>
                <el-table-column label="Sku图片">
                    <template #default="scope">
                        <el-upload class="avatar-uploader" :headers="headers"
                            action="http://192.168.1.188:8080/upload/admin" :show-file-list="false"
                            :on-success="uploadImage">
                            <img v-if="scope.row.img" :src="scope.row.img" class="avatar" />
                            <el-icon v-else @click="skuIndex = scope.$index">
                                <Upload />
                            </el-icon>
                        </el-upload>
                    </template>
                </el-table-column>
                <el-table-column label="条形码" width="180">
                    <template #default="scope">
                        <el-input v-model="scope.row.barCode" size="small">
                            <template #append>
                                <el-button @click="setBarCode(scope.row)">随机</el-button>
                            </template>
                        </el-input>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <div class="btn">
            <el-button @click="closePage">关闭</el-button>
            <el-button type="primary" @click="createWares(ruleFormRef)">保存商品</el-button>
        </div>
        <!-- 弹框 -->
        <el-dialog v-model="dialogFormVisible" :title="dialogStatus.title" width="600">
            <el-form :model="paramForm" label-position="left" label-width="120px" ref="ruleDialogRef">
                <div v-if="dialogStatus.status == 0">
                    <el-form-item label="商品参数名称" prop="attribute"
                        :rules="[{ required: true, message: '商品参数名称不能为空', trigger: 'blur' }]">
                        <el-input v-model="paramForm.attribute" autocomplete="off" />
                    </el-form-item>
                    <el-form-item label="商品参数值" prop="value"
                        :rules="[{ required: true, message: '商品参数值名称不能为空', trigger: 'blur' }]">
                        <el-input v-model="paramForm.value" autocomplete="off" />
                    </el-form-item>
                </div>
                <div v-if="dialogStatus.status == 1">
                    <el-form-item label="类型名称" prop="title"
                        :rules="[{ required: true, message: '类型名称不能为空', trigger: 'blur' }]">
                        <el-input v-model="paramForm.title" autocomplete="off" />
                    </el-form-item>
                </div>
                <div v-if="dialogStatus.status == 2">
                    <el-form-item label="现价(¥)" prop="price"
                        :rules="[{ required: true, message: '现价不能为空', trigger: 'blur' }]">
                        <el-input-number v-model="paramForm.price" :min="1" />
                    </el-form-item>
                    <el-form-item label="VIP价格(¥)" prop="vipPrice"
                        :rules="[{ required: true, message: 'VIP价格不能为空', trigger: 'blur' }]">
                        <el-input-number v-model="paramForm.vipPrice" :min="1" />
                    </el-form-item>
                    <el-form-item label="吊牌价(¥)" prop="originalPrice"
                        :rules="[{ required: true, message: '吊牌价不能为空', trigger: 'blur' }]">
                        <el-input-number v-model="paramForm.originalPrice" :min="1" />
                    </el-form-item>
                </div>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="dialogFormVisible = false">取消</el-button>
                    <el-button type="primary" @click="handleSetFoem(ruleDialogRef)">确定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import cookie from 'js-cookie';//引入处理cookies的Api
import { post } from "@/utils/http";//请求
import { initObj } from "@/utils/index";//处理初始化表单
import { formatTime } from "@/utils/time";//时间处理
import { useTagStore } from "@/stores/tags";
import { GoodsClass, SkuClass } from "#/index";//表单绑定数据
import { useRouter, useRoute } from 'vue-router';//路由跳转
import { ElMessage, ElMessageBox } from 'element-plus';//提示信息
import { Plus, Upload } from '@element-plus/icons-vue';//图标 
import type { UploadProps, FormInstance } from 'element-plus';//element数据类型


const ruleFormRef = ref<FormInstance>()//整体form表单节点
const ruleDialogRef = ref<FormInstance>() //弹框绑定表单节点
const store = useTagStore()//实例化状态管理函数
const route = useRoute()//实例化路由对象信息
const headers = reactive({ 'AdminToken': cookie.get('token') }) //头像上传添加token头
const categoryTreeData = reactive([] as any) //类目树形菜单数据
const freightData = reactive([] as any) //运费模板数据
const router = useRouter()//实例化路由函数
const dialogFormVisible = ref(false) //弹框是否显示
const inputTag = ref('') //商品详情tag添加绑定的数据
const formRules = { //表单验证规则
    title: [{ required: true, message: '商品名称不能为空', trigger: 'blur' }],
    originalPrice: [{ required: true, message: '原始价格不能为空', trigger: 'blur' }],
    price: [{ required: true, message: '当前价格不能为空', trigger: 'blur' }],
    vipPrice: [{ required: true, message: 'VIP价格不能为空', trigger: 'blur' }],
    status: [{ required: true, message: '请选择商品状态', trigger: 'blur' }],
    unit: [{ required: true, message: '商品单位不能为空', trigger: 'blur' }],
    detail: [{ required: true, message: '请填写商品详情', trigger: 'blur' }]
}

let specStatus = ref(false)//控制规格维度弹框状态 false:添加状态 true:修改状态
let dataForm = reactive(new GoodsClass()) //整体表单数据
let skuLength = ref(0)//商品(sku)详情表格长度
let skuIndex = ref(0)//商品(sku)详情表格下标
let specIndex = ref(0)//规格维度表格下标
let paramForm = reactive({ //弹框绑定表单
    title: '', //规格维度名称
    attribute: '', //商品参数名称
    value: '', //商品参数值
    price: 0.00,//批量定价 现价
    vipPrice: 0.00,//批量定价 VIP价格
    originalPrice: 0.00,//批量定价 吊牌价
})
let dialogStatus = ref({ //控制对话框状态和标题
    status: 0,
    title: ''
})

onMounted(() => {
    loadFreight()
})

// 头像上传
const handleAvatarSuccess: UploadProps['onSuccess'] = (
    response
) => {
    dataForm.imgList.push(response.url)
    dataForm.img = dataForm.imgList[0];
}

// 验证头像上传规则
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
    if (rawFile.type !== 'image/jpeg') {
        ElMessage.error('头像图片必须是JPG格式!')
        return false
    } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('头像图片大小不能超过2MB!')
        return false
    }
    return true
}

// 初始化运费模板数据
function loadFreight() {
    if (freightData.length == 0) {
        post({ _gp: 'admin.freight', _mt: 'list' }).then((res) => {
            console.log(res);
            let { data } = res;
            freightData.push(...data)
        })
    }
    CategoryTreeInfo()
}

// 初始化类目搜索数据
function CategoryTreeInfo() {
    if (categoryTreeData.length == 0) {
        post({ _gp: 'admin.category', _mt: 'categoryTree' }).then((res) => {
            console.log(res);
            let { data } = res;
            categoryTreeData.push(...data)
        })
    }
}

// 图片个数超出提示
function exceedTips() {
    ElMessage.warning('上传图片个数超出限制! 最多上传5张图片!')
}

// 商品参数添加事件
function WaresParamsAdd() {
    dialogFormVisible.value = true;
    dialogStatus.value = { status: 0, title: '设置商品参数' }
    initObj(paramForm);
    ruleDialogRef.value?.resetFields();//重置表单初始值
}

// 规格维度添加事件
function normsFormAdd() {
    dialogFormVisible.value = true;//显示弹框
    specStatus.value = false;
    dialogStatus.value = { status: 1, title: '创建规格' };
    initObj(paramForm);//初始化绑定表单数据
    ruleDialogRef.value?.resetFields();//重置表单初始值
}

//规格维度表格修改事件
function handleNormsEdit(index: number, row: { title: string }) {
    specIndex.value = index;//规格维度表格下标赋值
    dialogFormVisible.value = true;//显示弹框
    specStatus.value = true;//定义弹框为修改状态
    dialogStatus.value = { status: 1, title: '修改规格' };//定义弹框为规格维度弹框并处于修改状态
    ruleDialogRef.value?.resetFields();//重置表单初始值
    paramForm.title = row.title;
}

//批量定价添加事件
function batchPricing() {
    dialogFormVisible.value = true;
    dialogStatus.value = { status: 2, title: '批量定价' }
    initObj(paramForm);
    ruleDialogRef.value?.resetFields();//重置表单初始值
}

// 弹框确定
function handleSetFoem(formEl: FormInstance | undefined) {
    if (!formEl) return
    formEl.validate((valid: boolean) => {
        if (valid) {
            switch (dialogStatus.value.status) { //判断弹框状态
                case 0: //处于商品参数添加
                    let { attribute, value } = paramForm;
                    let attributeRepeat = dataForm.attributeList.findIndex((item) => item.attribute == attribute)
                    if (attributeRepeat > -1) { //商品参数去重 查找商品参数名称
                        ElMessage.warning('请不要添加重复属性');
                        return
                    } else {
                        dataForm.attributeList.push({ attribute, value });
                        ElMessage.success('添加成功');
                    }
                    break;
                case 1://处于规格维度添加
                    let { title } = paramForm
                    if (specStatus.value == false) { //处于规格维度添加状态
                        let specificationRepeat = dataForm.specificationList.findIndex((item) => item.title == title)
                        console.log(specificationRepeat);
                        if (specificationRepeat > -1) { //规格维度去重 查找维度名称
                            ElMessage.warning('请不要重复添加维度名称');
                            return
                        } else {
                            dataForm.specificationList.push({
                                title, //维度名称
                                gmtCreate: new Date().getTime(), //创建时间
                                gmtUpdate: 0,
                                inputSkuTagVisible: false, //点击tag添加是否显示input框
                                inputSkuTagValue: '',
                                values: []
                            })
                            ElMessage.success('添加成功');
                        }
                    } else if (specStatus.value == true) { //处于规格维度修改状态
                        dataForm.specificationList[specIndex.value].title = paramForm.title; //修改的维度名称赋给原来的维度名称
                        createSkuTable();
                        ElMessage.success('修改成功');
                    }
                    break;
                case 2://处于批量定价添加
                    let { price, originalPrice, vipPrice } = paramForm;
                    if (vipPrice <= price || price <= originalPrice) {
                        dataForm.skuList.forEach((i) => { //价格赋值
                            i.price = price;
                            i.originalPrice = originalPrice;
                            i.vipPrice = vipPrice;
                            return i
                        })
                    } else {
                        ElMessage.error('vip价必须小于现价且现价必须小于吊牌价');
                        return
                    }
                    break;
                default:
                    break;
            }
            dialogFormVisible.value = false;//弹框隐藏
        } else {
            return false
        }
    })
}

// 商品参数表格删除事件
function handleWaresDelete(index: number) {
    dataForm.attributeList.splice(index, 1)
    ElMessage.success('删除完成');
}

// 规格维度表格删除事件
function handleNormsDelete(index: number) {
    dataForm.specificationList.splice(index, 1);
    createSkuTable()
    ElMessage.success('删除完成');
}

// 商品(Sku)详情点击添加tag
function handleInputAdd(item: { inputSkuTagVisible: boolean }) {
    item.inputSkuTagVisible = true //显示input框
}

//商品详情input框失去焦点添加tag标签
function handleInputConfirm(item: { inputSkuTagVisible: boolean, values: Array<any> }) {
    if (inputTag.value) {
        let setIndex = item.values.indexOf(inputTag.value)
        setIndex == -1 ? item.values.push(inputTag.value) : ElMessage.warning('重复元素请不要添加')
    }
    inputTag.value = '';
    item.inputSkuTagVisible = false;
    createSkuTable()
}

//删除tag标签
function handleClose(ind: number, item: any) {
    item.values.splice(ind, 1)
    createSkuTable()
}

// 生成商品Sku详情表格
function createSkuTable() {
    const specList = dataForm.specificationList; //规格维度表格渲染数据
    const leachList = specList.filter(item => item.values.length).map(item => item.values);//获取所有的tag添加的数据
    const topic = specList.map(item => item.title);

    if (leachList.length == 0) {
        dataForm.skuList = [];
        return
    }

    // 根据属性值使用笛卡尔积算法将数据进行交叉处理
    var skuList = leachList.reduce((pre: string[][], next) => {
        var array: string[][] = [];
        pre.forEach((item) => {
            next.forEach((ites: string) => {
                array.push(item.concat([ites]))
            })
        })
        return array
    }, [[]])

    const { price, vipPrice, originalPrice } = paramForm;
    // 构建sku表格数据
    var skuTable = skuList.map((item: any, index: number) => {
        let obj: any = new SkuClass;//进行拼接数据
        Object.assign(obj, { price, vipPrice, originalPrice })
        item.forEach((val: any, index: number) => {
            obj['id_' + topic[index]] = val;
            obj.titleArray.push(topic[index]);
            obj.specificationArray.push(topic[index] + '_' + val)
        })
        obj.title = obj.titleArray.join(',')
        obj.specification = obj.specificationArray.join(',')
        return obj;
    })
    skuLength.value = skuTable.length;//生成的数组长度赋值给skuLength，即表格要生成的行数
    dataForm.skuList.length = 0;
    Object.assign(dataForm.skuList, skuTable);
}

//商品Sku详情表格合并
function objectSpanMethod({ row, column, rowIndex, columnIndex }: SpanMethodProps) {
    let { specificationList } = dataForm
    //拿到第一列要合并的行数
    if (specificationList.length > 0) {
        let inspce = specificationList.filter((v: any) => v.values.length)
        let rowspan = skuLength.value / inspce[0].values.length
        for (let index = 0; index < inspce.length; index++) {
            if (inspce[index].values.length == 0) {
                return
            }
            if (index !== 0) {
                //依次拿到每一列要合并的行数
                rowspan = rowspan / inspce[index].values.length;
            }
            if (columnIndex === index) {
                //当条件成立时，即合并行数
                if (rowIndex % rowspan === 0) {
                    return {
                        //合并的行数配置
                        rowspan: rowspan,
                        colspan: 1
                    };
                } else {
                    return {
                        rowspan: 0,
                        colspan: 0
                    };
                }
            }
        }
    }
}

// 随机生成条形码
function setBarCode(row: { barCode: string }) {
    row.barCode = + new Date() + '';
}

//商品sku详情表格上传图片
const uploadImage: UploadProps['onSuccess'] = (response) => {
    dataForm.skuList[skuIndex.value].img = response.url;
}

// 关闭页面
function closePage() {
    store.removeTagByPath(route.fullPath)
}

// 创建商品
function createWares(formEl: FormInstance | undefined) {
    if (!formEl) return
    formEl.validate((valid: boolean) => {
        if (valid) {
            post({ _gp: 'admin.product', _mt: 'create', spuDTO: JSON.stringify(dataForm) }).then((res) => {
                console.log(res);
                let { errmsg, errno } = res;
                if (200 == errno) {
                    ElMessageBox.confirm(
                        '商品创建成功,是否继续添加商品?',
                        '创建成功',
                        {
                            confirmButtonText: '继续',
                            cancelButtonText: '关闭',
                        }
                    ).then(() => {
                        initObj(dataForm)
                    }).catch(() => {
                        store.removeTagByPath(route.fullPath)
                    })
                } else {
                    ElMessage.error(errmsg)
                }
            })
        } else {
            ElMessage.warning('请完善以上表单')
        }
    })
}

</script>
<style lang="less" scoped>
.btn {
    margin-top: 20px;
    text-align: right;
}

.intro-card {
    width: 100%;

    h4 {
        margin-top: 0;
    }

    .el-form {
        width: 90%;
        margin: auto;

        .avatar {
            width: 178px;
            height: 178px;
        }
    }
}

.details-card {
    .skuTag {
        margin: 20px 0px;

        .el-button {
            margin-left: 5px;
        }

        .el-tag {
            margin-right: 5px;
        }

        .skuInput {
            margin-left: 10px;
            width: 100px;
        }
    }

    .avatar {
        width: 50px;
    }
}

.el-dialog {
    .el-form {
        width: 80%;
        margin: auto;
    }
}
</style>
